import { _decorator, Camera, Component, find, instantiate, Node, Prefab, Quat, tween, Tween, v3, Vec3 } from 'cc';
import { ZTool } from './ZTool';

export class NodeUtil {

    /*** 寻找子节点，所有子节点不能重名 */
    public static GetNode(name: string, rootNode: Node): Node {
        if (rootNode.name == name) {
            return rootNode;
        }
        for (let i = 0; i < rootNode.children.length; i++) {
            let node = this.GetNode(name, rootNode.children[i]);
            if (node) {
                return node;
            }
        }

        return null;
    }

    /*** 找到节点上的组件 */
    public static GetComponent<T extends Component>(name: string, rootNode: Node, type: { new(): T }): T | null {
        let node = this.GetNode(name, rootNode);
        if (node) {
            const component = node.getComponent(type);
            if (component) {
                return component;
            }
        }
        console.error(`Component ${type.name} not found on node ${node.name}`);
        return null;
    }

    /*** 实例化节点 */
    public static Instantiate(prefab: Prefab, parent: Node, position: Vec3 = Vec3.ZERO) {
        var node = instantiate(prefab);
        node.setParent(parent);
        node.setPosition(position);
        return node;
    }

    /*** 设置父物体 */
    public static SetParent(child: Node, parent: Node) {
        child.setParent(parent);
        child.setPosition(Vec3.ZERO);
        child.setRotationFromEuler(Vec3.ZERO);
        child.setScale(Vec3.ONE);
    }

    /*** 节点晃动 */
    public static Shaking(node: Node, repeat: number, timeGap: number, power: number, callback: Function = null) {
        Tween.stopAllByTarget(node);

        const x = node.position.x;
        const y = node.position.y;
        const z = node.position.z;

        let ts: Tween<Node>[] = [];
        for (let i = 0; i < repeat - 1; i++) {
            ts.push(tween(node).to(timeGap, { position: v3(x + ZTool.GetRandom(-power, power), y + ZTool.GetRandom(-power, power), z + ZTool.GetRandom(-power, power)) }));
        }
        ts.push(tween(node).to(timeGap, { position: v3(x, y, z) }));

        tween(node).sequence(...ts).call(() => { callback && callback() }).start();
    }

    public static WorldToScreen(camera: Camera, worldPosition: Vec3): Vec3 {
        return camera.convertToUINode(worldPosition, find("Canvas"));
    }

    /*** 获取两个坐标在 XZ 轴的距离 */
    public static GetXZDistance(aX: number, aZ: number, bX: number, bZ: number) {
        const x = aX - bX;
        const z = aZ - bZ;
        return Math.sqrt(x * x + z * z);
    }

}